//
// Created by wayne on 18-11-26.
//

#ifndef ENGINE_RACE_KEYLOGCACHE_H
#define ENGINE_RACE_KEYLOGCACHE_H

#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <atomic>
#include "constants.h"

namespace polar_race {


    class KeyLogCache {
    public:
        KeyLogCache() :
        keyLogId(-1), inUsed(0), completedPart(0),
        segmentCount(CacheSegmentCount), perCacheSize(PerCacheSize), partToFill(0) {
            pthread_mutex_init(&mutex, NULL);
            pthread_cond_init(&condition, NULL);
            posix_memalign(&cache, PerPartSize, PerCacheSize);
        }

        ~KeyLogCache() {
            pthread_mutex_destroy(&mutex);
            pthread_cond_destroy(&condition);
            free(cache);
        }

        int keyLogId;
        int inUsed;
        int completedPart;
        int segmentCount;
        int partToFill;
        size_t  perCacheSize;
        void *cache;
        pthread_mutex_t mutex;
        pthread_cond_t condition;

        int getPartToRead() {
            int part = -1;
            pthread_mutex_lock(&mutex);
            if(partToFill < segmentCount) {
                part = partToFill++;
            }
            pthread_mutex_unlock(&mutex);
            return part;
        }

        void setPartCompleted() {
            pthread_mutex_lock(&mutex);
            completedPart++;
            if(completedPart >= segmentCount) {
                pthread_cond_broadcast(&condition);
            }
            pthread_mutex_unlock(&mutex);
        }

        void waitCacheReady() {
            pthread_mutex_lock(&mutex);
            while (completedPart < segmentCount) {
                pthread_cond_wait(&condition, &mutex);
            }
            pthread_mutex_unlock(&mutex);
        }

        void releaseReference() {
            pthread_mutex_lock(&mutex);
            inUsed--;
            pthread_mutex_unlock(&mutex);
        }

    };

}


#endif //ENGINE_RACE_KEYLOGCACHE_H
